﻿using System;
using System.Buffers.Binary;

namespace WholeSlideImageLibrary.Formats.OptimizedPyramidTiledImage
{
    internal readonly struct FileMetadataBlock
    {
        public FileMetadataBlock(string name, FileMetadataItem[] items, long nextBlockPointer)
        {
            Name = name;
            Items = items;
            NextBlockPointer = nextBlockPointer;
        }

        public string Name { get; }
        public FileMetadataItem[] Items { get; }
        public long NextBlockPointer { get; }


        public static bool TryParse(ReadOnlySpan<byte> buffer, long totalFileSize, out FileMetadataBlock metadataBlock)
        {
            if (buffer.IsEmpty)
            {
                goto Failure;
            }
            int length = buffer[0];
            buffer = buffer.Slice(1);
            if (buffer.Length < length)
            {
                goto Failure;
            }
            string name = EncodingHelper.DecodeUtf8(buffer.Slice(0, length));
            buffer = buffer.Slice(length);
            if (buffer.Length < 2)
            {
                goto Failure;
            }
            int count = BinaryPrimitives.ReadUInt16LittleEndian(buffer);
            buffer = buffer.Slice(2);
            var items = new FileMetadataItem[count];
            for (int i = 0; i < count; i++)
            {
                if (!FileMetadataItem.TryParse(buffer, totalFileSize, out items[i], out int comsumed))
                {
                    goto Failure;
                }
                buffer = buffer.Slice(comsumed);
            }
            long nextBlockPointer = 0;
            if (buffer.Length >= 8)
            {
                nextBlockPointer = BinaryPrimitives.ReadInt64LittleEndian(buffer);
                if (nextBlockPointer < 0)
                {
                    nextBlockPointer += totalFileSize;
                }
            }
            metadataBlock = new FileMetadataBlock(name, items, nextBlockPointer);
            return true;
        Failure:
            metadataBlock = default;
            return false;
        }
    }
}
